/*!
\copyright  Copyright (c) 2022 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\brief
*/

#include "cap_server_role_advertising.h"
#include "le_advertising_manager.h"
#include "gatt_cas_server_uuids.h"

#include <logging.h>
#include <panic.h>
#include <stdlib.h>

#define CAP_SERVER_SIZE_ADVERT                  5
#define CAP_SERVER_ANNOUNCEMENT_TYPE_OCTET      4

/*! Service Data (16-bit default). */
#define CAP_BLE_AD_TYPE_SERVICE_DATA            0x16

#define CAP_DEBUG_INFO     DEBUG_LOG

typedef enum
{
    announcement_type_general,
    announcement_type_targeted
} CapAnnouncementType;

static le_adv_item_handle cap_server_registered_handle = NULL;
static le_adv_item_data_t cap_server_advert;

static const uint8 capServerAdvertData[CAP_SERVER_SIZE_ADVERT] = {
    CAP_SERVER_SIZE_ADVERT - 1,
    CAP_BLE_AD_TYPE_SERVICE_DATA,
    /* CAS UUID */
    UUID_COMMON_AUDIO_SERVICE  & 0xFF,
    UUID_COMMON_AUDIO_SERVICE  >> 8,
    /* 1 octet for Announcement Type */
    announcement_type_general,
};

static bool capServer_GetItemData(le_adv_item_data_t * item)
{
    if (cap_server_advert.data == NULL)
    {
        uint8 * data = NULL;

        data = PanicUnlessMalloc(CAP_SERVER_SIZE_ADVERT);
        memcpy(data, capServerAdvertData, CAP_SERVER_SIZE_ADVERT);

        cap_server_advert.data = data;
        cap_server_advert.size = CAP_SERVER_SIZE_ADVERT;

        CAP_DEBUG_INFO("capServer_GetAdvDataItem size:%d", cap_server_advert.size);
    }
    *item = cap_server_advert;
    return TRUE;
}

static void capServer_ReleaseItemData(void)
{
    if(cap_server_advert.data != NULL)
    {
        free((void *)cap_server_advert.data);
        cap_server_advert.data = NULL;
    }
}

#ifndef INCLUDE_LEGACY_LE_ADVERTISING_MANAGER

static bool capServer_GetItemInfo(le_adv_item_info_t * info)
{
    PanicNull(info);
    *info = (le_adv_item_info_t){ .placement = le_adv_item_data_placement_advert,
                                    .type = le_adv_type_extended_connectable,
                                    .data_size = CAP_SERVER_SIZE_ADVERT };
    return TRUE;
}

le_adv_item_callback_t capServer_AdvertisingManagerCallback =
{
    .GetItemData = &capServer_GetItemData,
    .ReleaseItemData = &capServer_ReleaseItemData,
    .GetItemInfo = &capServer_GetItemInfo
};

#else

#define CAP_SERVER_NUMBER_ADVERT_DATA_ITEMS     1

static bool capServer_CanAdvertise(const le_adv_data_params_t * params)
{
    bool can_advertise = FALSE;
    if (params->data_set == le_adv_data_set_extended_handset
            && params->completeness == le_adv_data_completeness_full
            && params->placement == le_adv_data_placement_advert)
    {
        can_advertise = TRUE;
    }

    return can_advertise;
}

static unsigned int capServer_GetNumberOfAdvertisingItems(const le_adv_data_params_t * params)
{
    if (capServer_CanAdvertise(params))
    {
        return CAP_SERVER_NUMBER_ADVERT_DATA_ITEMS;
    }
    return 0;
}



static le_adv_data_item_t capServer_GetAdvertisingData(const le_adv_data_params_t * params, unsigned int index)
{
    /* Only one adv data item supported. If more items are needed, this function must be updated */
    PanicFalse(index == 0);
    le_adv_data_item_t item = { .size = 0, .data = NULL };
    if (capServer_CanAdvertise(params))
    {
        capServer_GetItemData(&item);
        return item;
    }

    Panic();
    return item;
}

static void capServer_ReleaseAdvertisingData(const le_adv_data_params_t * params)
{
    UNUSED(params);
    capServer_ReleaseItemData();
}

le_adv_data_callback_t capServer_AdvertisingManagerCallback =
{
    .GetNumberOfItems = &capServer_GetNumberOfAdvertisingItems,
    .GetItem = &capServer_GetAdvertisingData,
    .ReleaseItems = &capServer_ReleaseAdvertisingData
};

#endif

bool CapServer_SetupLeAdvertisingData(void)
{
#ifndef INCLUDE_LEGACY_LE_ADVERTISING_MANAGER
    cap_server_registered_handle = LeAdvertisingManager_RegisterAdvertisingItemCallback(NULL, &capServer_AdvertisingManagerCallback);
#else
    cap_server_registered_handle = LeAdvertisingManager_Register(NULL, &capServer_AdvertisingManagerCallback);
#endif
    return (cap_server_registered_handle ? TRUE : FALSE);
}

bool CapServer_UpdateLeAdvertisingData(void)
{
#ifndef INCLUDE_LEGACY_LE_ADVERTISING_MANAGER
    return (cap_server_registered_handle ? LeAdvertisingManager_UpdateAdvertisingItem(cap_server_registered_handle) : FALSE);
#else
    return (cap_server_registered_handle ? LeAdvertisingManager_NotifyDataChange(NULL, cap_server_registered_handle) : FALSE);
#endif
}
